#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include "OneLineTemplate2.h"
#define STATE1 1
#define STATE2 2
#define STATE3 3
#define STATE4 4

int OLTInit(const char* text , OneLineTemplate *tpl)
{
    OneLineTemplateNode newNode;
    size_t textIndex     = 0;
    int    state         = STATE1;
    char   currentChr    = 0;
    char   token[1024]   = {0};
    size_t tokenIndex = 0;

    while((currentChr = text[textIndex++]) != '\0')
    {
        if (STATE1 == state)
        {
            if ('{' != currentChr)
            {
                //commone char, just put it into token
                token[tokenIndex++] = currentChr;
            }
            else
            {
                //about to get a var, first need to save token if needed
                if (0 != tokenIndex)
                {
                    token[tokenIndex] = '\0';
                    newNode.dataType = DATATYPE_CONSTTEXT;
                    newNode.dataVal  = token;
                    //insert into list;
                    tpl->push_back(newNode);
                }
                //reset tokenIndex for further use, and state change to STATE2
                tokenIndex = 0;
                state      = STATE2;
            }
        }
        else if (STATE2 == state)
        {
            if ((currentChr >= 'a' && currentChr <= 'z') ||
                (currentChr >= 'A' && currentChr <= 'Z'))
            {
                //var char, put it into token
                token[tokenIndex++] = currentChr;
                state = STATE3;
            }
            else
            {
                //error, expecting [a-zA-Z]
                state = STATE4;
            }
        }
        else if(STATE3 == state)
        {
            if ((currentChr >= 'a' && currentChr <= 'z') ||
                    (currentChr >= 'A' && currentChr <= 'Z') ||
                    (currentChr >= '0' && currentChr <= '9'))
            {
                //var char, put it into token
                token[tokenIndex++] = currentChr;
            }
            else if('}' == currentChr)
            {
                //got a var
                token[tokenIndex]    = '\0';
                newNode.dataType     = DATATYPE_VARINDEX;
                newNode.dataVal      = token;
                //insert into list;
                tpl->push_back(newNode);
                //reset tokenIndex
                tokenIndex = 0;
                state = STATE1;
            }
            else
            {
                //error, expecting [a-zA-Z0-9}]
                state = STATE4;
            }
        }
        else if (STATE4 == state)
        {
            //error state
            tpl->clear();
            break;
        }
    }

    if (STATE1 == state)
    {
        if (0 != tokenIndex)
        {
            token[tokenIndex] = '\0';
            newNode.dataType = DATATYPE_CONSTTEXT;
            newNode.dataVal  = token;
            tpl->push_back(newNode);
        }
    }
    else
    {
        tpl->clear();
        return -1;
    }
    return 0;
}

string  OLTFormat(const OneLineTemplate *tpl , const SymTable *symtable)
{
	stringstream ss;
	for(OneLineTemplate::const_iterator it = tpl->begin(); it != tpl->end(); it++)
    {
        if (DATATYPE_CONSTTEXT == it->dataType)
        {
            ss << it->dataVal;
        }
        else
        {
            ss << symtable->find(it->dataVal)->second;
        }
    }
    return ss.str();
}

string OLTFormat(const char* text, const SymTable *symtable)
{
	OneLineTemplate tpl;
	if(0 == OLTInit(text, &tpl))
	{
        return OLTFormat(&tpl, symtable);
    }
    else
	{
      //TODO: throw exception
  }
}
